using System;

namespace SharpMud.MudLib.SAMPLE.Environment
{
	/// <summary>
	/// Used to effectively 'manage' directional values.
	/// Lists and parses directional values/keywords and everything.
	/// </summary>
	[AttributeUsage(System.AttributeTargets.Field)]
	public class ExitDirectionKeywordsAttribute : System.Attribute
	{
		#region Private Variables
		private string[] _Keywords;
		#endregion

		#region Constructors
		public ExitDirectionKeywordsAttribute()
			:this(new string[] {})
		{
		}

		public ExitDirectionKeywordsAttribute(params string[] keywords)
		{
			this._Keywords = keywords;
		}
		#endregion

		#region Public Propertes
		public string[] Keywords
		{
			get
			{
				return _Keywords;
			}
		}
		#endregion

		#region Static Stuff
		/// <summary>
		/// Uses reflection to get the keywords for the given exit value.
#if !DEBUG
		/// Will return an empty array if there are problems finding the keywords.
#else
		/// May return an empty array if there are problems finding the keywords.
#endif
		/// </summary>
		/// <param name="exitDirection">The direction for which keywords we are looing</param>
		/// <returns>Returns a string array of the keywords for the exit direction given</returns>
		public static string[] FindKeywordsForDirection(ExitDirection exitDirection)
		{
#if !DEBUG
			try
			{
#endif
			System.Reflection.FieldInfo field = 
				(typeof(ExitDirection)).GetField(exitDirection.ToString());
			if(field==null)
				return new string[] {};

			ExitDirectionKeywordsAttribute[] EDKAs = (ExitDirectionKeywordsAttribute[])field.GetCustomAttributes(typeof(ExitDirectionKeywordsAttribute),true);
			if(EDKAs==null)
				return new string[] {};
			if(EDKAs.Length==0)
				return new string[] {};

			return EDKAs[0].Keywords;
#if !DEBUG
			}
			catch
			{
				return new string[] {};
			}
#endif
		}

		/// <summary>
		/// Attempts to determine a directional value given a string that may or may not match
		/// pre-defined directional keywords.
		/// </summary>
		/// <param name="keyword">The keyword that is supposed to represent a direction</param>
		/// <returns>Returns the matching ExitDirection</returns>
		/// <exception cref="ArgumentNullException">Thrown when 'keyword' is either Null or equal to String.Empty</exception>
		/// <exception cref="ArgumentOutOfRangeException">Thrown when 'keyword' does not match a recognized directional keyword</exception>
		public static ExitDirection FindDirectionForKeyword(string keyword)
		{
			if(keyword==null)
				throw new ArgumentNullException("keyword");
			if(keyword.Trim()==string.Empty)
				throw new ArgumentNullException("keyword");

			string s = keyword.ToLower().Trim();

			System.Collections.ArrayList sc = new System.Collections.ArrayList();

			foreach(System.Reflection.FieldInfo field in (typeof(ExitDirection)).GetFields())
			{
				sc.Clear();
				ExitDirectionKeywordsAttribute[] EDKAs = (ExitDirectionKeywordsAttribute[])field.GetCustomAttributes(typeof(ExitDirectionKeywordsAttribute),true);
				if(EDKAs==null)
					continue;
				if(EDKAs.Length==0)
					continue;
				foreach(ExitDirectionKeywordsAttribute edka in EDKAs)
				{
					sc.AddRange(edka.Keywords);
				}
				foreach(string g in sc)
				{
					if(s==g.ToLower().Trim())
					{
						return (ExitDirection)System.Enum.Parse(typeof(ExitDirection),field.Name,true);
					}
				}
			}
			throw new ArgumentOutOfRangeException("keyword",keyword,"The directional keyword was not recognized.");
		}

		/// <summary>
		/// Gets all the keywords associated with directional movement
		/// </summary>
		public static string[] GetAllKeywords()
		{
			System.Collections.ArrayList sc = new System.Collections.ArrayList();
			foreach(System.Reflection.FieldInfo field in (typeof(ExitDirection)).GetFields())
			{
				ExitDirectionKeywordsAttribute[] EDKAs = (ExitDirectionKeywordsAttribute[])field.GetCustomAttributes(typeof(ExitDirectionKeywordsAttribute),true);
				if(EDKAs==null)
					continue;
				if(EDKAs.Length==0)
					continue;
				foreach(ExitDirectionKeywordsAttribute edka in EDKAs)
				{
					sc.AddRange(edka.Keywords);
				}
			}
			return (string[])sc.ToArray(typeof(string));
		}

		/// <summary>
		/// Gets all the directional movement directions
		/// </summary>
		/// <returns></returns>
		public static ExitDirection[] GetAllDirections()
		{
			System.Collections.ArrayList al = new System.Collections.ArrayList();
			foreach(System.Reflection.FieldInfo field in (typeof(ExitDirection)).GetFields())
			{
				ExitDirection ed = (ExitDirection)System.Enum.Parse(typeof(ExitDirection),field.Name,true);
				if(al.Contains(ed)==false)
					al.Add(ed);
			}
			return (ExitDirection[])al.ToArray(typeof(ExitDirection));
		}
		#endregion
	}
}
